Skip to content

[blackwell_kihlstrom.md] Update np.random → Generator API#890

Open
Chihiro2000GitHub wants to merge 1 commit into
mainfrom
update-rng-blackwell-kihlstrom
Open

[blackwell_kihlstrom.md] Update np.random → Generator API#890
Chihiro2000GitHub wants to merge 1 commit into
mainfrom
update-rng-blackwell-kihlstrom

Conversation

@Chihiro2000GitHub

Copy link
Copy Markdown
Contributor

Summary

This PR migrates legacy NumPy random API usage in blackwell_kihlstrom.md as part of QuantEcon/meta#299.

Details

  • Replaced np.random.seed(0) with rng = np.random.default_rng(0) in the imports block.
  • Updated sample_posteriors to accept rng=rng as a default argument and replaced the two internal np.random.choice(...) calls with rng.choice(...).
  • Call sites for sample_posteriors are unchanged — the module-level rng is used by default.
  • sequential_update and check_martingale_mean were already using the Generator API and required no changes.
  • No fixed seed was introduced beyond what the original np.random.seed(0) already provided.
  • No Numba-related code in this lecture.

Hi @mmcky and @HumphreyYang, I'd be grateful if you could take a look when you have time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

📖 Netlify Preview Ready!

Preview URL: https://pr-890--sunny-cactus-210e3e.netlify.app

Commit: ae964e8

📚 Changed Lectures


Build Info

@mmcky mmcky left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Chihiro2000GitHub! The migration is correct and behaviour-preserving. Just one optional consistency nit inline about aligning sample_posteriors with the seed-based pattern already used by sequential_update / check_martingale_mean in this lecture. Otherwise good to go. (Worth a quick look at the Netlify preview to confirm the simplex clouds still read well, since the seeded stream changes under Generator.)

@HumphreyYang — could you weigh in on the inline suggestion? It's a judgment call about which RNG idiom to standardise on within a lecture (module-level rng vs. seed-per-function), so I'd like your read before we ask for changes.

name: fig-blackwell-simplex-clouds
---
def sample_posteriors(μ_matrix, prior, n_draws=3000):
def sample_posteriors(μ_matrix, prior, n_draws=3000, rng=rng):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Chihiro2000GitHub — this is correct and faithfully preserves the original behaviour (the two sample_posteriors calls still draw sequentially from a single stream).

One small consistency point: this lecture already has two sibling functions, sequential_update and check_martingale_mean, that take a seed and build the generator locally (rng = np.random.default_rng(seed)). With this change sample_posteriors instead relies on a module-level rng injected via a rng=rng default argument, so the lecture ends up with two different RNG idioms for three very similar functions.

Could we align sample_posteriors with its siblings by building the generator in the driver (plot_simplex_posteriors) and passing it in? That keeps a single shared stream (so the μ and ν clouds stay independent, as now), removes the module-level global, and lets us drop the np.random.seed(0) line at the top. Something like:

def sample_posteriors(μ_matrix, prior, n_draws=3000, rng=None):
    """..."""
    if rng is None:
        rng = np.random.default_rng()
    N, M = μ_matrix.shape
    states = rng.choice(N, size=n_draws, p=prior)
    signals = np.array([rng.choice(M, p=μ_matrix[s]) for s in states])
    ...

and then in plot_simplex_posteriors:

def plot_simplex_posteriors(μ_matrix, ν_matrix, prior3, n_draws=3000, seed=0):
    rng = np.random.default_rng(seed)
    posts_μ = sample_posteriors(μ_matrix, prior3, n_draws, rng)
    posts_ν = sample_posteriors(ν_matrix, prior3, n_draws, rng)
    ...

With that, the rng = np.random.default_rng(0) line in the imports block can be removed. Non-blocking — happy either way, but it would make the three functions consistent.

@HumphreyYang HumphreyYang Jun 17, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks @mmcky, that makes sense.

I agree that creating the generator locally in plot_simplex_posteriors is
cleaner and keeps the RNG pattern consistent with sequential_update and
check_martingale_mean.

Changing to

posts_μ = sample_posteriors(μ_matrix, prior3, n_draws, rng=rng)
posts_ν = sample_posteriors(ν_matrix, prior3, n_draws, rng=rng)

also makes it explicit that both posterior samples are drawn using the same
local generator.

After making this change, we can drop the global

rng = np.random.default_rng(0)

because it was only being used as the default value for rng in
sample_posteriors.

I think it is a strict improvement and should be adopted everywhere else!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmcky @HumphreyYang,

Thank you both! I'll go through your comments later, probably this weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants